package org.xx.armory.spring5.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.xx.armory.commons.ForLogging;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static java.util.Arrays.asList;
import static org.xx.armory.commons.Validators.rejectIfBlank;

/**
 * 验证固定内置帐户的验证器。
 */
public class FixedAuthenticationProvider
        extends AbstractArmoryUserPasswordAuthenticationProvider
        implements AuthenticationProvider {
    @ForLogging
    private final Logger logger = LoggerFactory.getLogger(FixedAuthenticationProvider.class);

    private final Map<String, User_> users;

    public FixedAuthenticationProvider() {
        this.users = new HashMap<>();
    }

    public FixedAuthenticationProvider addUser(
            String userName,
            CharSequence password,
            GrantedAuthority... authorities
    ) {
        userName = rejectIfBlank(userName, "userName").trim();

        this.users.put(userName, new User_(userName, password, asList(authorities)));

        return this;
    }

    @Override
    protected Collection<? extends GrantedAuthority> authenticate(
            String username,
            CharSequence password,
            ArmoryWebAuthenticationDetails details
    )
            throws AuthenticationException {
        final var u = this.users.get(username);

        if (u == null) {
            return null;
        }

        return u.getAuthorities();
    }

    private static class User_ {
        private final String userName;
        private final CharSequence password;
        private final Collection<GrantedAuthority> authorities;

        public User_(
                String userName,
                CharSequence password,
                Collection<? extends GrantedAuthority> authorities
        ) {
            this.userName = userName;
            this.password = password;
            this.authorities = new ArrayList<>(authorities);
        }

        public String getUserName() {
            return this.userName;
        }

        public CharSequence getPassword() {
            return this.password;
        }

        public Collection<GrantedAuthority> getAuthorities() {
            return this.authorities;
        }
    }
}
